package com.ruoyi.common.utils.validator;

import com.ruoyi.common.enums.BaseEnum;
import com.ruoyi.common.utils.validator.constraints.CheckEnum;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.poi.ss.formula.functions.T;

/**
 * CheckEnumValidator
 *
 * @author ruoyi
 **/
public class CheckEnumValidator implements ConstraintValidator<CheckEnum, T> {

    private Class<?> enumClass;

    @Override
    public void initialize(CheckEnum constraintAnnotation) {
        enumClass = constraintAnnotation.enumClass();
    }

    @Override
    public boolean isValid(T value, ConstraintValidatorContext context) {
        Type[] types = enumClass.getGenericInterfaces();
        if (!needValidate(types)) {
            return true;
        }
        try {
            return validate(value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 是否需要校验
     * 只有implements接口BaseIntEnum，才能校验
     */
    private boolean needValidate(Type[] types) {
        //是否需要校验
        boolean needValidate = false;
        for (Type type : types) {
            if (type.getTypeName().equals(BaseEnum.class.getName())) {
                needValidate = true;
            }
        }
        return needValidate;
    }

    /**
     * 遍历枚举code值，校验value是否存在其中
     */
    private boolean validate(T value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method valuesMethod = enumClass.getMethod("values");
        if (null == valuesMethod) {
            return true;
        }
        BaseEnum[] inter = (BaseEnum[]) valuesMethod.invoke(null);
        for (BaseEnum iter : inter) {
            if (iter.getCode().equals(value)) {
                return true;
            }
        }
        return false;
    }

}
